/**
  ******************************************************************************
  * @author     Chris
  * @since      2023/10/12 22:59
  *
  * @file       sd_encode.c
  * @brief      Xxx Hardware Driver.
  *
  * @note       This file contains the hardware driver for the Xxx.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date           Author       Notes
  *   2023/10/12     Chris        the first version
  *
  ******************************************************************************
  */

#include "stm32g4xx.h"
#include "hd_lcd.h"

/** region Declaration and Definition Region */

/** region Variables and Constants Region */

/** endregion Variables and Constants Region */

/** region Function Declaration Region */

/** endregion Function Declaration Region */

/** endregion Declaration and Definition Region */


/** region Public Definition Region */

/**
 * @brief   获取 UTF-8 编码的汉字字节数
 *
 * @note    转换规则如下：
 *           n |  Unicode符号范围(HEX)  |  UTF-8编码方式(二进制，n 位为 1，n+1 位为 0，ASCII 除外)
 *          ---+-----------------------+------------------------------------------------------
 *           1 | 0000 0000 - 0000 007F |                                              0xxxxxxx
 *           2 | 0000 0080 - 0000 07FF |                                     110xxxxx 10xxxxxx
 *           3 | 0000 0800 - 0000 FFFF |                            1110xxxx 10xxxxxx 10xxxxxx
 *           4 | 0001 0000 - 0010 FFFF |                   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
 *           5 | 0020 0000 - 03FF FFFF |          111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
 *           6 | 0400 0000 - 7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
 *          ---+-----------------------+------------------------------------------------------
 * @param   chr 汉字的首字节
 * @retval  汉字字节数
 */
uint8_t get_utf8_size(uint8_t chr) {
    if ((chr >> 4) == 0x0E) { return 3; }       // 3 个字节时，前 3 位为 1110（最常见）
    else if ((chr >> 7) == 0x00) { return 1; }  // 1 个字节时，前 1 位为 0（兼容的 ASCII）
    else if ((chr >> 5) == 0x06) { return 2; }  // 2 个字节时，前 2 位为 110
    else if ((chr >> 3) == 0x1E) { return 4; }  // 4 个字节时，前 1 位为 1111 0
    else if ((chr >> 2) == 0x3E) { return 5; }  // 5 个字节时，前 1 位为 1111 10
    else if ((chr >> 1) == 0x7E) { return 6; }  // 6 个字节时，前 1 位为 1111 110
    else { return 0; }                          // 错误
}

/**
 * @brief   获取 UTF-8 编码的汉字的 Unicode 编码
 *
 * @note    转换规则如下：
 *           n |  Unicode符号范围(HEX)  |  UTF-8编码方式(二进制，n 位为 1，n+1 位为 0，ASCII 除外)
 *          ---+-----------------------+------------------------------------------------------
 *           1 | 0000 0000 - 0000 007F |                                              0xxxxxxx
 *           2 | 0000 0080 - 0000 07FF |                                     110xxxxx 10xxxxxx
 *           3 | 0000 0800 - 0000 FFFF |                            1110xxxx 10xxxxxx 10xxxxxx
 *           4 | 0001 0000 - 0010 FFFF |                   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
 *           5 | 0020 0000 - 03FF FFFF |          111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
 *           6 | 0400 0000 - 7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
 *          ---+-----------------------+------------------------------------------------------
 * @param   str 汉字编码的首字节地址
 * @retval  Unicode 编码
 */
uint32_t utf8_2_unicode(const uint8_t *str) {
    const uint8_t size = get_utf8_size(*str);

    uint64_t utf8 = 0;
    for (int i = 0; i < size; ++i) {
        utf8 <<= 8;
        utf8 |= *(str + i);
    }

    if (utf8 <= 0x7F) { return utf8; }  // 1 个字节，直接返回
    else if ((utf8 <= 0x7FF)) {         // 2 个字节，取前 5 后 6 位
        uint64_t a;
        a = (utf8 >> 8) & 0x1F;
        a <<= 6;
        a |= (utf8 >> 0) & 0x3F;
        return a;
    } else if ((utf8 <= 0xFFFF)) {      // 3 个字节，1 取 4，2 取 6，3 取 6 位
        uint64_t a;
        a = (utf8 >> 16) & 0x0F;
        a <<= 6;
        a |= (utf8 >> 8) & 0x3F;
        a <<= 6;
        a |= (utf8 >> 0) & 0x3F;
        return a;
    } else if ((utf8 <= 0x1FFFF)) {     // 4 个字节，1 取 3，2 取 6，3 取 6，4 取 6 位
        uint64_t a;
        a = (utf8 >> 24) & 0x07;
        a <<= 6;
        a |= (utf8 >> 16) & 0x3F;
        a <<= 6;
        a |= (utf8 >> 8) & 0x3F;
        a <<= 6;
        a |= (utf8 >> 0) & 0x3F;
        return a;
    } else {
        return 0;
    }
}

/** endregion Public Definition Region */


/** region Private Definition Region */

/** endregion Private Definition Region */
